//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package org_evaluate_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/org_eval_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/org_evaluate_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *OrgEvaluateApiImpl) GetMyEvaluate(ctx context.Context, req *org_evaluate_api.GetMyEvaluateRequest) (*org_evaluate_api.GetMyEvaluateResponse, error) {
	emptyList := []*org_evaluate_api.MyEvaluateResult{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ResultList: emptyList,
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_NO_ORG,
			ErrMsg:     "组织不存在",
			ResultList: emptyList,
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ResultList: emptyList,
		}, nil
	}
	evaluateItem, err := org_eval_dao.EvaluateDao.Get(ctx, req.OrgId, req.EvaluateId)
	if err != nil {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_NO_EVALUATE,
			ErrMsg:     "评估不存在",
			ResultList: emptyList,
		}, nil
	}
	if evaluateItem.EvaluateState == uint32(org_evaluate_api.EVALUATE_STATE_EVALUATE_STATE_DRAFT) {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_WRONG_STATE,
			ErrMsg:     "处于草稿阶段",
			ResultList: emptyList,
		}, nil
	}
	canVote := false
	for _, memberUserId := range evaluateItem.MemberUserIdList {
		if memberUserId == sessionItem.UserId {
			canVote = true
		}
	}
	if !canVote {
		return &org_evaluate_api.GetMyEvaluateResponse{
			Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ResultList: emptyList,
		}, nil
	}

	voteItemList, err := org_eval_dao.VoteScoreDao.ListByVoteUser(ctx, req.OrgId, req.EvaluateId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	voteScoreMap := map[string]uint32{}
	for _, voteItem := range voteItemList {
		voteScoreMap[voteItem.VoteId] = voteItem.Score
	}
	//获取成员信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, evaluateItem.MemberUserIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//获取评估指标列表
	targetItemList, err := org_eval_dao.TargetDao.List(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	targetNameMap := map[string]string{}
	for _, targetItem := range targetItemList {
		targetNameMap[targetItem.TargetId] = targetItem.TargetName
	}
	//生成结果
	resultList := []*org_evaluate_api.MyEvaluateResult{}
	for _, memberUserId := range evaluateItem.MemberUserIdList {
		result := &org_evaluate_api.MyEvaluateResult{
			MemberUserId: memberUserId,
			ScoreList:    []*org_evaluate_api.EvaluateTargetScore{},
		}
		userItem, ok := userItemMap[memberUserId]
		if ok {
			result.MemberDisplayName = userItem.BasicInfo.DisplayName
			result.MemberLogoUri = userItem.BasicInfo.LogoUri
		}
		for _, targetId := range evaluateItem.TargetIdList {
			voteId := org_eval_dao.VoteScoreDao.GenVoteId(req.EvaluateId, sessionItem.UserId, memberUserId, targetId)
			result.ScoreList = append(result.ScoreList, &org_evaluate_api.EvaluateTargetScore{
				TargetId:   targetId,
				TargetName: targetNameMap[targetId],
				Score:      voteScoreMap[voteId],
			})
		}
		resultList = append(resultList, result)
	}

	return &org_evaluate_api.GetMyEvaluateResponse{
		Code:       org_evaluate_api.GetMyEvaluateResponse_CODE_OK,
		ResultList: resultList,
	}, nil
}

func (apiImpl *OrgEvaluateApiImpl) UpdateMyEvaluate(ctx context.Context, req *org_evaluate_api.UpdateMyEvaluateRequest) (*org_evaluate_api.UpdateMyEvaluateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	evaluateItem, err := org_eval_dao.EvaluateDao.Get(ctx, req.OrgId, req.EvaluateId)
	if err != nil {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_NO_EVALUATE,
			ErrMsg: "评估不存在",
		}, nil
	}
	if evaluateItem.EvaluateState != uint32(org_evaluate_api.EVALUATE_STATE_EVALUATE_STATE_EVALUATE) {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_WRONG_STATE,
			ErrMsg: "非评估阶段",
		}, nil
	}
	canVote := false
	for _, memberUserId := range evaluateItem.MemberUserIdList {
		if memberUserId == sessionItem.UserId {
			canVote = true
		}
	}
	if !canVote {
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查成员和评估指标是否匹配
	memberUserIdMap := map[string]int{}
	for _, memberUserId := range evaluateItem.MemberUserIdList {
		memberUserIdMap[memberUserId] = 1
	}
	targetIdMap := map[string]int{}
	for _, targetId := range evaluateItem.TargetIdList {
		targetIdMap[targetId] = 1
	}
	for _, item := range req.ItemList {
		memberUserIdMap[item.MemberUserId] = memberUserIdMap[item.MemberUserId] + 1
		for _, scoreItem := range item.ScoreList {
			targetIdMap[scoreItem.TargetId] = targetIdMap[scoreItem.TargetId] + 1
		}
	}
	for _, count := range memberUserIdMap {
		if count != 2 {
			return &org_evaluate_api.UpdateMyEvaluateResponse{
				Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_WRONG_MEMBER,
				ErrMsg: "成员不匹配",
			}, nil
		}
	}
	rightTargetCount := len(evaluateItem.MemberUserIdList) + 1
	for _, count := range targetIdMap {
		if count != rightTargetCount {
			return &org_evaluate_api.UpdateMyEvaluateResponse{
				Code:   org_evaluate_api.UpdateMyEvaluateResponse_CODE_WRONG_TARGET,
				ErrMsg: "评估指标不匹配",
			}, nil
		}
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//删除投票记录
		err = org_eval_dao.VoteScoreDao.RemoveByVoteUser(sessCtx, req.OrgId, req.EvaluateId, sessionItem.UserId)
		if err != nil {
			return nil, err
		}
		//增加投票记录
		for _, item := range req.ItemList {
			for _, scoreItem := range item.ScoreList {
				if scoreItem.Score > 10 {
					scoreItem.Score = 10 //分数范围0-10分
				}
				err = org_eval_dao.VoteScoreDao.Insert(sessCtx, &org_eval_dao.VoteScoreDbItem{
					OrgId:        req.OrgId,
					EvaluateId:   req.EvaluateId,
					VoteUserId:   sessionItem.UserId,
					MemberUserId: item.MemberUserId,
					TargetId:     scoreItem.TargetId,
					Score:        scoreItem.Score,
				})
				if err != nil {
					return nil, err
				}
			}
		}
		//重新计算结果
		voteItemList, err := org_eval_dao.VoteScoreDao.ListByEvaluate(sessCtx, req.OrgId, req.EvaluateId)
		if err != nil {
			return nil, err
		}
		resultItemMap := map[string]*org_eval_dao.ResultScoreDbItem{}
		for _, voteItem := range voteItemList {
			resultId := org_eval_dao.ResultScoreDao.GenResultId(req.EvaluateId, voteItem.MemberUserId, voteItem.TargetId)
			resultItem, ok := resultItemMap[resultId]
			if !ok {
				resultItem = &org_eval_dao.ResultScoreDbItem{
					ResultId:     resultId,
					OrgId:        req.OrgId,
					EvaluateId:   req.EvaluateId,
					MemberUserId: voteItem.MemberUserId,
					TargetId:     voteItem.TargetId,
					TotalScore:   0,
				}
				resultItemMap[resultId] = resultItem
			}
			resultItem.TotalScore += voteItem.Score
		}
		for _, resultItem := range resultItemMap {
			err = org_eval_dao.ResultScoreDao.UpdateScore(sessCtx, resultItem)
			if err != nil {
				return nil, err
			}
		}
		return &org_evaluate_api.UpdateMyEvaluateResponse{
			Code: org_evaluate_api.UpdateMyEvaluateResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*org_evaluate_api.UpdateMyEvaluateResponse), nil
}
